Counters Deques and namedtuples

Comment with meaning

Created: Sep 10th 2019
Updated: December 7th 2019
Connect with us on
image
image

Counter's, deque's, and namedtuple's are built in python datatypes as part of the collections standard library module. They each are useful in their own way, and are well worth learning.

Definitions

Some terms to help you navigate the post

Counter's

Counters are a data structure used to... well count. You can add objects into the counter and you will get a tally of each object. This is most commonly used with a list of strings to tally how many occurrences of a word in text there are. Here is the code for that:

from collections import Counter
import string # Used to get a list of punctuation

text = """Do not go gentle into that good night
Old age should burn and rave at close of day
Rage rage against the dying of the light

Though wise men at their end know dark is right
Because their words had forked no lightning they
Do not go gentle into that good night

Good men the last wave by crying how bright
Their frail deeds might have danced in a green bay
Rage rage against the dying of the light

Wild men who caught and sang the sun in flight
And learn too late they grieved it on its way
Do not go gentle into that good night

Grave men near death who see with blinding sight
Blind eyes could blaze like meteors and be gay
Rage rage against the dying of the light

And you my father there on the sad height
Curse bless me now with your fierce tears I pray
Do not go gentle into that good night
Rage rage against the dying of the light"""

text = text.replace("\n","").lower() # Remove newlines and set all text to lowercase
words = [] # Placeholder list to be filled with each word

for word in text.split(): # Iterate over text and add it to list
    words.append(word)

count = Counter(words) # Count occurences of strings in the list

print(count)

Which will print:

>> Counter({'the': 11, 'of': 5, 'not': 4, 'go': 4, 'gentle': 4, 'into': 4, 'that': 4, 'good': 4, 'rage': 4, 'against': 4, 'dying': 4, 'men': 4, 'and': 3, 'at': 2, 'their': 2, 'in': 2, 'who': 2, 'on': 2, 'with': 2, 'do': 1, 'nightold': 1, 'age': 1, 'should': 1, 'burn': 1, 'rave': 1, 'close': 1, 'dayrage': 1, 'lightthough': 1, 'wise': 1, 'end': 1, 'know': 1, 'dark': 1, 'is': 1, 'rightbecause': 1, 'words': 1, 'had': 1, 'forked': 1, 'no': 1, 'lightning': 1, 'theydo': 1, 'nightgood': 1, 'last': 1, 'wave': 1, 'by': 1, 'crying': 1, 'how': 1, 'brighttheir': 1, 'frail': 1, 'deeds': 1, 'might': 1, 'have': 1, 'danced': 1, 'a': 1, 'green': 1, 'bayrage': 1, 'lightwild': 1, 'caught': 1, 'sang': 1, 'sun': 1, 'flightand': 1, 'learn': 1, 'too': 1, 'late': 1, 'they': 1, 'grieved': 1, 'it': 1, 'its': 1, 'waydo': 1, 'nightgrave': 1, 'near': 1, 'death': 1, 'see': 1, 'blinding': 1, 'sightblind': 1, 'eyes': 1, 'could': 1, 'blaze': 1, 'like': 1, 'meteors': 1, 'be': 1, 'gayrage': 1, 'lightand': 1, 'you': 1, 'my': 1, 'father': 1, 'there': 1, 'sad': 1, 'heightcurse': 1, 'bless': 1, 'me': 1, 'now': 1, 'your': 1, 'fierce': 1, 'tears': 1, 'i': 1, 'praydo': 1, 'nightrage': 1, 'light': 1})

dequeu's

A collection that can be used as a queue or a stack depending on what you need. It also allows you to append to the left or right of the dequeue. An example use case could be a queueing system that keeps track of peoples position in a lineup:

from collections import deque

my_queue = deque(["james","john","tommy","emilia","Candace"])

for line_location in range(len(my_queue)):
    print(f"Next in line is: {my_queue.pop()}")

namedtuple's

Can be used as a psuedo-class if you want just attributes. It is used in cases where a class may have too much overhead, but you need a named collection of data or even an immutable collection of data then namedtuples are your way to go. Here is an example of a user namedtuple implementation:

from collections import namedtuple

# Create namedtuple 'Template' 
user = namedtuple("User" ,"name, age, birthday, join_date, premium")

# Allows you to specify IMMUTABLE instances in a class-like syntax
john_doe = user("John Doe", 20, "September 26th 1998", "September 9th 2019", True)

print(john_doe) # Prints: User(name='John Doe', age=20, birthday='September 26th 1998', join_date='September 9th 2019', premium=True)

Usage

All demo's in this repository have no dependencies and can be run using python <file_name>.py or python3 <file_name>.py.

Real World Applications

All of these collection types have various uses, Counters are often used in games to keep track of inventory, dequeues are used in event and theme park queuing systems to keep track of peoples places in line, and namedtuples are used all over the place for optimization.

Additional Information

The key thing to take away from this is learning enough about these collections to use them in convenient ways. You should also take a look at the other collections available in the standard library as some of them surprised me to have a python implementation. You can find the docs for the collection module here.

Files

counter_demo.py

from collections import Counter

# Instantiate a counter instance with a list
fruit_counter = Counter(['apple','orange','banana','apple'])

# You can also create/update counters with keyword arguments
fruit_counter.update(banana=75, apple=3)

# You can also use a dictionary
fruit_counter.update({"orange":45, "banana":113, "apple":90})

# Default __repr__ prints all items and their counts
print(f"Fruit counter: {fruit_counter}")

# instance.most_common() prints elements in descending order
print(f"Most common: {fruit_counter.most_common()}")

dequeue_demo.py

from collections import deque

my_queue = deque(["james","john","tommy","emilia","Candace"])

# The pop() method removes items from the queue and returns them
print(f"{my_queue.pop()} has been removed from queue")

for line_location in range(len(my_queue)):
    """Because my_queue.pop() is called in the iteration, the
    deque object ends up being empty"""
    print(f"{my_queue.pop()} was in position {line_location + 1}")
    print(f"Queue is empty: {my_queue}") # will be empty now
# .append() appends iterable/object to rightmost of the queue
my_queue.append("joanna")

# Be careful, this appends the list to the queue, not each item
my_queue.append(["julia", "frank"])

# Appends an iterable/object to the leftmost of the queue
my_queue.appendleft("david")

namedtuple_demo.py

from collections import namedtuple

# Create namedtuple 'Template'
user = namedtuple("User" ,"name, age, birthday, join_date, premium")

# Allows you to specify IMMUTABLE instances in a class-like syntax
john_doe = user("John Doe", 20, "September 26th 1998", "September 9th 2019", True)

# namedtuple's have a built in __repr__ that is not bad
print(f"There is a user: {john_doe}")

# namedtuple's are also iterable
for attribute in john_doe:
    print(attribute)

Thank you for your support!

Be sure to share the post if it was helpful!